package service

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"strings"
	"time"

	"detection-web/internal/dao"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/gclient"
)

// IHttpClient HTTP客户端服务接口
type IHttpClient interface {
	CallWechatAPI(ctx context.Context, finderUsername, cookie string) ([]byte, error)
	CallWechatAPIConcurrent(ctx context.Context, finderUsernames []string) (map[string][]byte, error)
}

// httpClientService HTTP客户端服务实现
type httpClientService struct{}

var localHttpClient IHttpClient

// HttpClient 获取HTTP客户端服务实例
func HttpClient() IHttpClient {
	if localHttpClient == nil {
		localHttpClient = &httpClientService{}
	}
	return localHttpClient
}

// getAvailableCookies 获取可用的Cookie列表
func (s *httpClientService) getAvailableCookies(ctx context.Context) ([]string, error) {
	// 从item_account表获取第一个Cookie
	dbCookie, err := dao.ItemAccount.GetFirstCookie(ctx)
	if err != nil {
		return nil, fmt.Errorf("从数据库获取Cookie失败: %v", err)
	}
	if dbCookie == "" {
		return nil, fmt.Errorf("数据库中没有可用的Cookie")
	}
	return []string{dbCookie}, nil
}

// isValidCookieFormat 检查Cookie格式是否有效
func (s *httpClientService) isValidCookieFormat(cookie string) bool {
	return strings.Contains(cookie, "promotewebsessionid") && len(cookie) > 50
}

// CallWechatAPI 调用微信API（增强版）
func (s *httpClientService) CallWechatAPI(ctx context.Context, finderUsername, cookie string) ([]byte, error) {
	// 验证Cookie格式
	if !s.isValidCookieFormat(cookie) {
		return nil, fmt.Errorf("Cookie格式无效")
	}

	// 构造请求体
	reqBody := map[string]interface{}{
		"encryptedUsername": finderUsername,
		"limit":             20,
		"baseReq": struct {
			FeatureFlag int `json:"featureFlag"`
		}{
			FeatureFlag: 26,
		},
	}

	// 序列化请求体
	jsonData, err := json.Marshal(reqBody)
	if err != nil {
		return nil, fmt.Errorf("序列化请求体失败: %v", err)
	}

	// 创建HTTP客户端
	client := gclient.New()
	client.SetTimeout(30 * time.Second)

	// 设置请求头
	client.SetHeader("Cookie", cookie)
	client.SetHeader("Content-Type", "application/json")
	client.SetHeader("Accept", "application/json, text/plain, */*")
	client.SetHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
	client.SetHeader("Referer", "https://channels.weixin.qq.com/")

	url := "https://channels.weixin.qq.com/promote/api/web/transfer/MmFinderPromotionApiSvr/getFinderObject"

	// 发送POST请求
	resp, err := client.Post(ctx, url, jsonData)
	if err != nil {
		if strings.Contains(err.Error(), "timeout") || strings.Contains(err.Error(), "deadline exceeded") {
			return nil, fmt.Errorf("请求超时: 服务器响应时间超过30秒，请检查网络连接或稍后重试")
		}
		return nil, fmt.Errorf("请求失败: %v", err)
	}
	if resp == nil {
		return nil, fmt.Errorf("响应为空")
	}
	defer resp.Close()

	// 读取响应内容
	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应内容失败: %v", err)
	}

	responseStr := string(responseBody)
	g.Log().Debugf(ctx, "API响应状态码: %d, 内容长度: %d", resp.StatusCode, len(responseStr))
	// 添加响应内容的前100个字符用于调试
	if len(responseStr) > 100 {
		g.Log().Debugf(ctx, "响应内容前100字符: %s", responseStr[:100])
	} else {
		g.Log().Debugf(ctx, "完整响应内容: %s", responseStr)
	}

	// 检查认证错误
	if strings.Contains(responseStr, `"returnCode":-333`) || strings.Contains(responseStr, `"returnCode":-334`) ||
		strings.Contains(responseStr, `"errcode":-333`) || strings.Contains(responseStr, `"errcode":-334`) ||
		strings.Contains(responseStr, `"errcode":-360`) || // 新增-360错误码检测
		strings.Contains(responseStr, "登陆态已失效") || strings.Contains(responseStr, "请重新登陆") {
		return nil, fmt.Errorf("认证失败: Cookie已过期或无效，请更新Cookie后重试")
	}

	return responseBody, nil
}

// CallWechatAPIConcurrent 改进的并发调用API
func (s *httpClientService) CallWechatAPIConcurrent(ctx context.Context, finderUsernames []string) (map[string][]byte, error) {
	// 获取可用的Cookie列表
	cookies, err := s.getAvailableCookies(ctx)
	if err != nil {
		return nil, fmt.Errorf("获取Cookie失败: %v", err)
	}

	results := make(map[string][]byte)
	cookieIndex := 0
	maxRetries := 2 // 最大重试次数

	g.Log().Infof(ctx, "开始处理，总共 %d 条请求，可用Cookie数量: %d", len(finderUsernames), len(cookies))

	// 逐个处理每个请求
	for i, username := range finderUsernames {
		g.Log().Infof(ctx, "正在处理第 %d/%d 个请求: %s", i+1, len(finderUsernames), username)

		var data []byte
		var lastErr error
		success := false

		// 重试逻辑
		for retry := 0; retry <= maxRetries && !success; retry++ {
			// 选择Cookie（轮换使用）
			currentCookie := cookies[cookieIndex%len(cookies)]

			if retry > 0 {
				g.Log().Infof(ctx, "第 %d 次重试请求 [%s]，使用Cookie索引: %d", retry, username, cookieIndex%len(cookies))
			}

			// 调用API
			data, lastErr = s.CallWechatAPI(ctx, username, currentCookie)
			if lastErr == nil {
				success = true
				results[username] = data
				g.Log().Infof(ctx, "请求成功 [%s]: 响应数据长度 %d 字节", username, len(data))
			} else {
				g.Log().Warningf(ctx, "请求失败 [%s] (尝试 %d/%d): %v", username, retry+1, maxRetries+1, lastErr)

				// 如果是认证失败，尝试下一个Cookie
				if strings.Contains(lastErr.Error(), "认证失败") {
					cookieIndex++
					if cookieIndex >= len(cookies) {
						// 所有Cookie都试过了，重置索引
						cookieIndex = 0
					}
				}

				// 重试前等待
				if retry < maxRetries {
					// time.Sleep(1 * time.Second)
				}
			}
		}

		if !success {
			g.Log().Errorf(ctx, "请求最终失败 [%s]: %v", username, lastErr)
		}

		// 成功或失败后都要等待1秒再处理下一个请求
		if i < len(finderUsernames)-1 {
			// g.Log().Infof(ctx, "完成处理第 %d/%d 个请求，等待1秒后继续...", i+1, len(finderUsernames))  // 注释掉延时相关日志
			g.Log().Infof(ctx, "完成处理第 %d/%d 个请求，继续下一个...", i+1, len(finderUsernames)) // 修改日志消息
			// time.Sleep(1 * time.Second)
		}

		// 轮换到下一个Cookie
		cookieIndex++
	}

	g.Log().Infof(ctx, "所有API请求处理完成，成功: %d/%d", len(results), len(finderUsernames))
	return results, nil
}
